#include "PollDispatcher.h"

// 实例化PollDispatcher
PollDispatcher::PollDispatcher(EventLoop* evLoop) : Dispatcher(evLoop), _maxfd(0) {
	_fds = new struct pollfd[_capacity];
	for (int i = 0; i < _capacity; ++i) {
		_fds[i].fd = -1;
		_fds[i].events = 0;
		_fds[i].revents = 0;
	}
	_name = "poll";
}

// 销毁PollDispatcher
PollDispatcher::~PollDispatcher() { delete[] _fds; }

// 将[_curChannel.fd]添加到poll模型
int PollDispatcher::add() {
	int events = 0;
	if (_curChannel->getEvents() & static_cast<int>(FdEvent::_ReadEvent)) { events |= POLLIN; }
	if (_curChannel->getEvents() & static_cast<int>(FdEvent::_WriteEvent)) { events |= POLLOUT; }
	int i = 0;
	for (; i < _capacity; ++i) {
		if (_fds[i].fd == -1) {
			_fds[i].fd = _curChannel->getFd();
			_fds[i].events = events;
			_maxfd = (i > _maxfd) ? i : _maxfd;
			break;
		}
	}
	if (i >= _capacity) { return -1; }
	return 0;
}

// 将[_curChannel.fd]从poll模型中删除, 并释放_curChannel所属的TcpConnection
int PollDispatcher::remove() {
	// 1. 将[_curChannel.fd]从poll模型中删除
	int i = 0;
	for (; i < _capacity; ++i) {
		if (_fds[i].fd == _curChannel->getFd()) {
			_fds[i].fd = -1;
			_fds[i].events = 0;
			_fds[i].revents = 0;
			break;
		}
	}
	if (i >= _capacity) { return -1; }

	// 2. 释放_curChannel所属的TcpConnection
	_curChannel->_destroyCallback(const_cast<void*>(_curChannel->getArg()));
	return 0;
}

// 修改poll模型中的[_curChannel.fd]的属性
int PollDispatcher::modify() {
	int events = 0;
	if (_curChannel->getEvents() & static_cast<int>(FdEvent::_ReadEvent)) { events |= POLLIN; }
	if (_curChannel->getEvents() & static_cast<int>(FdEvent::_WriteEvent)) { events |= POLLOUT; }
	int i = 0;
	for (; i < _capacity; ++i) {
		if (_fds[i].fd == _curChannel->getFd()) {
			_fds[i].events = events;
			break;
		}
	}
	if (i >= _capacity) { return -1; }
	return 0;
}

// 检测poll模型上的[_curChannel.fd]是否被激活(是否有就绪事件), 阻塞等待timeout秒, 并处理就绪事件
int PollDispatcher::dispatch(int timeout) {
	// 1. 等待事件就绪
	int count = poll(_fds, _maxfd + 1, timeout * 1000);
	if (count == -1) {
		LogDebug("poll error!");
		return -1;
	}

	// 2. 处理就绪事件
	for (int i = 0; i <= _maxfd; ++i) {
		if (_fds[i].fd == -1) { continue; }
		if (_fds[i].revents & POLLERR || _fds[i].revents & POLLHUP) { // �Զ˶Ͽ�����
			continue;
		}
		if (_fds[i].revents & POLLIN) {  // ���¼�����
			_eventLoop->eventActive(_fds[i].fd, static_cast<int>(FdEvent::_ReadEvent));
		}
		if (_fds[i].revents & POLLOUT) { // д�¼�����
			_eventLoop->eventActive(_fds[i].fd, static_cast<int>(FdEvent::_WriteEvent));
		}
	}
	return 0;
}
